package com.wechat.face;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.swak.Constants;
import com.swak.utils.IOUtils;
import com.swak.utils.Lists;
import com.swak.utils.Maps;
import com.swak.utils.StringUtils;

/**
 * 表情的管理
 * 
 * @author 618lf
 */
public class Faces {
	private static Map<String, Category> categorys = Maps.newOrderMap();
	private static Map<Category, Map<String, Face>> faces = Maps.newOrderMap();
	private static Map<String, Face> indexs = Maps.newHashMap();

	static {
		try {
			loadClassical();
		} catch (Exception e) {
		}
		try {
			loadEmotion();
		} catch (Exception e) {
		}
	}

	static void loadClassical() throws IOException {
		Category category = categorys.computeIfAbsent("classical",
				(key) -> new Category().setKey("classical").setName("经典"));
		Map<String, Face> categoryFaces = faces.computeIfAbsent(category, (key) -> Maps.newOrderMap());

		List<String> lines = Lists.newArrayList();
		InputStream is = Faces.class.getResourceAsStream("/face/classical/face.txt");
		lines = IOUtils.readLines(is, Constants.DEFAULT_ENCODING);
		IOUtils.closeQuietly(is);

		String path = "/face/classical/";
		String showSuffix = ".png";
		String realSuffix = ".gif";

		for (String name : lines) {
			String[] array = name.split(",");
			if (array.length > 1) {
				String key = array[0];
				String text = array[1];
				String showFileName = key + showSuffix;
				String realFileName = key + realSuffix;
				URL showUrl = Faces.class.getResource(path + "png/" + showFileName);
				URL realUrl = Faces.class.getResource(path + "gif/" + realFileName);
				Face face = new Face();
				face.setCg(category.getKey());
				face.setKey(key);
				face.setShowPath(showUrl);
				face.setRealPath(realUrl);
				face.setText(text);
				face.setHeight(24);
				face.setWidth(24);
				categoryFaces.put(key, face);
				indexs.put(face.Index(), face);
			}
		}

		// cover
		category.setFace(findFace("classical@14"));
	}

	static void loadEmotion() throws IOException {
		Category category = categorys.computeIfAbsent("emotion",
				(key) -> new Category().setKey("emotion").setName("表情"));
		Map<String, Face> categoryFaces = faces.computeIfAbsent(category, (key) -> Maps.newOrderMap());
		List<String> lines = Lists.newArrayList();
		InputStream is = Faces.class.getResourceAsStream("/face/emotion/face.txt");
		lines = IOUtils.readLines(is, Constants.DEFAULT_ENCODING);
		IOUtils.closeQuietly(is);

		String path = "/face/emotion/";
		String suffix = ".png";

		for (String name : lines) {
			String[] array = name.split(",");
			if (array.length > 1) {
				String key = array[0];
				String text = array[1];
				URL url = Faces.class.getResource(path + key + suffix);
				Face face = new Face();
				face.setCg(category.getKey());
				face.setKey(key);
				face.setShowPath(url);
				face.setRealPath(url);
				face.setText(text);
				face.setHeight(32);
				face.setWidth(32);
				categoryFaces.put(key, face);
				indexs.put(face.Index(), face);
			}
		}

		// cover
		category.setFace(findFace("emotion@emotion_001"));
	}

	public static Collection<Category> getCategorys() {
		return categorys.values();
	}

	public static List<Face> findFaces(Category category) {
		Map<String, Face> map = faces.get(category);
		return Lists.newArrayList(map.values());
	}

	public static Face findFace(String keyName) {
		if (StringUtils.isBlank(keyName)) {
			return null;
		}
		return indexs.get(keyName);
	}

	public static List<Object> parseString(String string) {
		if (StringUtils.isBlank(string)) {
			return Nones;
		}
		List<Object> results = Lists.newArrayList();
		int lastEnd = 0;
		Matcher matcher = Face_Pattern.matcher(string);
		while (matcher.find()) {
			String lastText = string.substring(lastEnd, matcher.start());
			if (StringUtils.isNotBlank(lastText)) {
				results.add(lastText);
			}
			String keyName = matcher.group(1);
			Face face = Faces.findFace(keyName);
			results.add(face == null ? matcher.group(0) : face);
			lastEnd = matcher.end();
		}
		String lastText = string.substring(lastEnd);
		if (!lastText.isEmpty()) {
			results.add(lastText);
		}
		return results;
	}

	public static String parseBriefString(String string) {
		List<Object> texts = parseString(string);
		StringBuilder brief = new StringBuilder();
		for (Object text : texts) {
			String append = StringUtils.EMPTY;
			if (text instanceof String) {
				append = (String) text;
			} else if (text instanceof Face) {
				append = ((Face) text).Encode();
			}
			if (brief.length() + append.length() <= 255) {
				brief.append(append);
			}
			if (brief.length() >= 255) {
				break;
			}
		}
		return brief.toString();
	}

	static final String Face_Mark = ":";
	static final String Face_Split = "@";
	static final Pattern Face_Pattern = Pattern.compile(":([^:]+):");
	static final List<Object> Nones = Lists.newArrayList(1);
}